iT邦幫忙

2023 iThome 鐵人賽

DAY 4
1
Modern Web

那些你可能要知道的前端知識系列 第 4

【day4】(Javascript) 提升Hoisting

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20230907/20148303y9uEkcwZAX.png

什麼是Hoisting?

Hoisting 稱作「提升」,會將變數宣告函式宣告提升到它們所在作用域的頂部,但要注意賦值不會被提升。

先來看一段程式碼進入狀況~

console.log(a) // 輸出 undefined
var a = "今天喝拿鐵"

從這個程式碼可以看出,為什麼在a被宣告之前可以拿得到undefined值(?)
實際上在瀏覽器(編譯器)中是長這樣子 ↓

var a
console.log(a) // undefined
a = "今天喝拿鐵"

有發現var a像是被提升到最上方了嗎?這就是「提升Hoisting」
因為賦值不會被提升,所以只有var a(變數宣告)被拉到這個作用域(Scope)的最上方。

為什麼會說「像是」被提升到最上方?
因為在程式碼在實際上的位置還會一樣的,並不會真的移動到程式碼,當我們說的變數提升或是函式被提升時,實際上是在編譯階段中先將它們放在記憶體中。


暫時性死區(Temporal Dead Zone)

有提升(Hoisting)的特性,還是都會強烈建議先宣告完後再使用
在ES6之後,大部分的開發者已經棄用var來宣告變數,改為使用letconst
為什麼?
使用letconst再宣告之前呼叫就會拋出ReferenceError,而不是undefined

console.log(drink)

let drink = "明天喝冰美式" // 錯誤:ReferenceError

如果在letconst宣告之前呼叫,瀏覽器會報錯誤訊息,而不是undefined,這個情況就稱之為「暫時性死區(Temporal Dead Zone)」。


函式提升

如果是使用function定義則屬於「函式宣告」
先來看看程式碼

qq(5,5) // 想想看這邊會印出什麼?

function qq(a,b){
    return a * b
}

公佈正解:qq(5,5)會印出25
為什麼?我明明是在function定義完之前呼叫,怎麼不會報錯呢?
原因是「函式提升」與「變數提升」的差別在於,「函式提升」會將函式全部(包括內容)往上提升而且優先權比較高,因此上面的程式碼會輸出function而不是undefined~!


總結

最後來整理出Hoisting的要點

  • 變數宣告、函式宣告都有提升的現象
  • 賦值不會提升

為了避免遇到Hoisting的情況,還是強烈建議先定義好再使用,也可以養成寫程式良好的習慣唷!

參考資料
MDN
我知道你懂 hoisting,可是你了解到多深?


上一篇
【day3】(JavaScript) 作用域 Scope
下一篇
【day5】(JavaScript) 閉包 Closure
系列文
那些你可能要知道的前端知識30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言